﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ZedGraph;

namespace UNSWThink
{
   public partial class GraphResponsesTabForm : Form
   {
      private DataTable questions;
      private DataTable answers;
      private DataTable responses;

      private ArrayList questionTotals;
      private ArrayList totalsError;
      private int offset;

      public GraphResponsesTabForm(DataTable relatedQuestions, DataTable relatedAnswers, DataTable relatedResponses)
      {
         InitializeComponent();

         this.questions = relatedQuestions;
         this.answers = relatedAnswers;
         this.responses = relatedResponses;

         questionTotals = new ArrayList();
         totalsError = new ArrayList();

         offset = 0;
      }

      private void GraphResponsesTabForm_Load(object sender, EventArgs e)
      {
         // create tabs for each question
         if ((HelperMethods.CheckColumnsExists(questions, Defs.QUESTION_COLUMN_NAMES)) &&
             (HelperMethods.CheckColumnsExists(answers, Defs.ANSWER_COLUMN_NAMES)))
         {
            for (int i = 0; i < questions.Rows.Count; i++)
            //for (int i = questions.Rows.Count - 1; i >= 0; i--)
            {
               //int questionNum = (int)questions.Rows[i]["number"];
               int fakeQuestionNum = i + 1;

               ZedGraphControl newGraphControl = new ZedGraphControl();
               newGraphControl.Dock = System.Windows.Forms.DockStyle.Fill;
               newGraphControl.Name = CreateGraphControlName(fakeQuestionNum);

               TabPage tempTabPage = new TabPage();
               tempTabPage.Controls.Add(newGraphControl);
               tempTabPage.Name = CreateTabControlName(fakeQuestionNum);
               tempTabPage.TabIndex = fakeQuestionNum;
               tempTabPage.Text = "Question " + fakeQuestionNum;

               tabControlQuestions.TabPages.Add(tempTabPage);

               int questionID = (int)questions.Rows[i]["id"];
               int realQuestionNum = (int)questions.Rows[i]["number"];
               QuestionType questionType = HelperMethods.QuestionTypeStringToEnum(
                  questions.Rows[i]["type"].ToString());
               QuestionTotal newQuestionTotal = new QuestionTotal(questionID, realQuestionNum);

               if ((questionType == QuestionType.MCQ) || (questionType == QuestionType.OPN))
               {
                  for (int j = 0; j < answers.Rows.Count; j++)
                  {
                     if ((int)answers.Rows[j]["question"] == questionID)
                     {
                        ResponseTotal newTotal = new ResponseTotal(answers.Rows[j]["description"].ToString());
                        newQuestionTotal.Totals.Add(newTotal);
                     }
                  }
               }
               else if (questionType == QuestionType.TFQ)
               {
                  ResponseTotal newTotal1 = new ResponseTotal("true");
                  newQuestionTotal.Totals.Add(newTotal1);

                  ResponseTotal newTotal2 = new ResponseTotal("false");
                  newQuestionTotal.Totals.Add(newTotal2);
               }

               questionTotals.Add(newQuestionTotal);
            }
         }

         // check responses contain expected table column name precondition
         if (HelperMethods.CheckColumnsExists(responses, Defs.RESPONSE_COLUMN_NAMES))
         {
            // loop through responses table to change the totals
            for (int i = 0; i < responses.Rows.Count; i++)
            {
               IncrementTotal((int)responses.Rows[i]["question"], 
                  responses.Rows[i]["description"].ToString());
            }
         }

         offset = responses.Rows.Count;

         InitGraph();
      }

      private string CreateGraphControlName(int questionNum)
      {
         return ("zgc" + questionNum.ToString());
      }

      private string CreateTabControlName(int questionNum)
      {
         return ("tabPage" + questionNum.ToString());
      }

      private int GetNumberFromTabName(string tabPageName)
      {
         string stringNum = tabPageName.Substring(7);
         return Int32.Parse(stringNum);
      }

      /// <summary>
      /// Modifies the ResponseTotal list for a given answer
      /// </summary>
      /// <param name="answerDescription">
      /// The answer which is to be used for the comparison
      /// </param>
      private void IncrementTotal(int questionID, string answerDescription)
      {
         // search the ResponseTotal list for matching answer
         foreach (QuestionTotal quesTotal in questionTotals)
         {
            if (quesTotal.QuestionID == questionID)
            {
               foreach (ResponseTotal respTotal in quesTotal.Totals)
               {
                  // if answer matches, increment the currentTotal and return from the method
                  if (respTotal.Answer == answerDescription)
                  {
                     respTotal.CurrentTotal++;
                     return;
                  }
               }
            }
         }
      }

      /// <summary>
      /// Initialises the graph to display the totals
      /// </summary>
      private void InitGraph()
      {
         foreach (TabPage graphPage in tabControlQuestions.TabPages)
         {
            int tabNumber = GetNumberFromTabName(graphPage.Name);

            foreach (QuestionTotal quesTotal in questionTotals)
            {
               if (quesTotal.QuestionNum == tabNumber)
               {
                  // init various graph properties
                  string graphName = CreateGraphControlName(tabNumber);
                  ZedGraphControl zgc = (ZedGraphControl)graphPage.Controls[graphName];
                  GraphPane myPane = zgc.GraphPane;
                  myPane.CurveList.Clear();
                  myPane.GraphObjList.Clear();
                  BarSettings bs = myPane.BarSettings;

                  // TODO: possibly need to have specific case for each question type
                  // set the title and axis labels
                  myPane.Title.Text = "Responses for Question " + tabNumber + " (Right-click on graph for menu)";
                  myPane.XAxis.Title.Text = "Totals";
                  myPane.YAxis.Title.Text = "Answers";
                  String[] labels = HelperMethods.ParseStringArray(quesTotal.Totals);
                  myPane.YAxis.Scale.TextLabels = labels;
                  myPane.YAxis.Type = AxisType.Text;

                  // generate point list from totals list
                  PointPairList list = new PointPairList();
                  foreach (ResponseTotal total in quesTotal.Totals)
                  {
                     list.Add(total.CurrentTotal, 0);
                  }

                  // create new curve
                  BarItem myCurve = myPane.AddBar("", list, Color.Blue);
                  myCurve.Bar.Fill = new Fill(Color.Blue, Color.White, Color.Blue, 90);

                  // set BarBase to the YAxis for horizontal bars
                  myPane.BarSettings.Base = BarBase.Y;

                  // fill the chart background with a color gradient
                  myPane.Chart.Fill = new Fill(Color.White,
                     Color.FromArgb(255, 255, 166), 45.0F);

                  // update the axis for current points
                  zgc.AxisChange();

                  // create TextObj's to provide labels for each bar
                  BarItem.CreateBarLabels(myPane, false, "f0");
                  zgc.Refresh();

                  break;
               }
            }
         }
      }

      /// <summary>
      /// Updates the form's graph with the latest responses
      /// </summary>
      public void UpdateGraph()
      {
         if (offset < responses.Rows.Count)
         {
            if (HelperMethods.CheckColumnsExists(responses, Defs.RESPONSE_COLUMN_NAMES))
            {
               for (int i = offset; i < responses.Rows.Count; i++)
               {
                  IncrementTotal((int)responses.Rows[i]["question"],
                     responses.Rows[i]["description"].ToString());
               }
            }
            offset = responses.Rows.Count;

            InitGraph();
         }
      }
   }
}
